package me.zhengjie.service.impl;

import lombok.RequiredArgsConstructor;
import me.zhengjie.WcsReport.WcsReportService;
import me.zhengjie.agvSend.AgvSendService;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.pojo.vo.ReturnVo;
import me.zhengjie.pojo.vo.TestVo;
import me.zhengjie.service.PdaService;
import me.zhengjie.sqlservice.*;
import me.zhengjie.util.state.TaskStatus;
import me.zhengjie.util.state.TaskType;
import me.zhengjie.utility.IdWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class PdaServiceImpl implements PdaService {
    private static final Logger pda = LoggerFactory.getLogger("pda");

    private final IwsSOutsideService iwsSOutsideService;

    private final AgvSendService agvSendService;

    private final IdWorker idWorker;

    private final WcsDeliveryMissionService wcsDeliveryMissionService;

    private final WcsReportService wcsReportService;

    private final WcsInboundMissionService wcsInboundMissionService;

    private final NestingMiddleTableService nestingMiddleTableService;


    //点对点叫车
    @Override
    @Transactional
    public boolean pdaPointToPointCallCar(PdaPointToPointCallCarDto pdaPointToPointCallCarDto) {
        Integer floor = pdaPointToPointCallCarDto.getFloor();
        String storageCode = pdaPointToPointCallCarDto.getStorageCode();
        if (floor == 2) {
            //根据楼层查询库外下料点是否有储位
            List<IwsSOutside> iwsSOutsides = iwsSOutsideService.selectStoreTypeStatus(TaskType.STORAGE_TYPE_TWE_FLOOR_CUTTING_POINT.getMessage(), 0);
            if (!iwsSOutsides.isEmpty()) {
                IwsSOutside iwsSOutside = iwsSOutsides.get(0);
                String destinationCode = iwsSOutside.getId();
                //储位绑定栈板
                CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
                carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
                carrierUnbindDto.setSlotCode(storageCode);
                carrierUnbindDto.setCarrierCategory("PALLET");
                carrierUnbindDto.setCarrierType("1");
                carrierUnbindDto.setInvoke(TaskType.BIND.getMessage());
                agvSendService.carrierUnbind(carrierUnbindDto);
                //2，楼下料点有储位，下发AGV任务
                AgvTaskSubmitDto agvTaskSubmitDto = new AgvTaskSubmitDto();
                //todo 任务类型，根据现场情况来定
                agvTaskSubmitDto.setTaskType(TaskType.PF_FMR_COMMON.getMessage());
                ArrayList<TargetRoute> targetRouteList = new ArrayList<>();
                TargetRoute targetRoute = new TargetRoute();
                TargetRoute targetRoutes = new TargetRoute();
                //添加起点
                targetRoute.setSeq(0);
                targetRoute.setType(TaskType.SITE.getMessage());
                targetRoute.setCode(storageCode);
                //添加终点
                targetRoutes.setSeq(1);
                targetRoutes.setType(TaskType.SITE.getMessage());
                targetRoutes.setCode(destinationCode);
                targetRouteList.add(targetRoute);
                targetRouteList.add(targetRoutes);
                agvTaskSubmitDto.setTargetRoute(targetRouteList);
                String deliveryCode = String.valueOf(idWorker.nextId());
                agvTaskSubmitDto.setRobotTaskCode(deliveryCode);
                agvTaskSubmitDto.setInitPriority(99);
                String taskCode = agvSendService.agvTaskSubmit(agvTaskSubmitDto);
                if (taskCode != null) {
                    //将终点储位绑定
                    boolean b = iwsSOutsideService.updateStatus(destinationCode, null, 1);
                    if (!b) {
                        pda.error("点对点去2楼修改终点储位状态失败");
                        throw new RuntimeException("点对点去2楼修改终点储位状态失败");
                    }
                    //创建配送任务
                    WcsDeliveryMission wcsDeliveryMission = new WcsDeliveryMission();
                    wcsDeliveryMission.setDeliveryCode(taskCode);
                    wcsDeliveryMission.setMissionStatus(TaskStatus.task_send.getStatus());
                    wcsDeliveryMission.setSource(storageCode);
                    wcsDeliveryMission.setDestination(destinationCode);
                    wcsDeliveryMission.setCreateTime(LocalDateTime.now());
                    wcsDeliveryMission.setUpdateTime(LocalDateTime.now());
                    wcsDeliveryMission.setContainerType(TaskType.PALLET.getStatus());
                    boolean b1 = wcsDeliveryMissionService.insertDelivery(wcsDeliveryMission);
                    if (!b1) {
                        pda.error("点对点叫车，创建配送任务失败，数据库异常");
                        throw new RuntimeException("点对点叫车，创建配送任务失败，数据库异常");
                    }
                }
            }
        }
        return false;
    }

//    @Override
//    public ReturnVo circleLibrary(String storageCode) {
//        //将储位信息发送给WMS获取栈板信息
//        ReturnVo returnVo = wcsReportService.circleLibraryObtainPalletCode(storageCode);
//        pda.info("1楼回库请求参数：{},获取栈板信息：{}", storageCode, returnVo);
//        if (returnVo.getCode() != 200) {
//            return returnVo;
//        }
//        String palletCode = (String) returnVo.getData();
//        InboundStorageApplyDto1 inboundStorageApplyDto = new InboundStorageApplyDto1();
//        inboundStorageApplyDto.setContainerCode(palletCode);
//        inboundStorageApplyDto.setFloor(String.valueOf(TaskType.ONE_FLOOR.getMessage()));
//        inboundStorageApplyDto.setNest(true);
////        List<NestingMiddleTable> nestingMiddleTables = nestingMiddleTableService.selectContainerCode(palletCode);
//        inboundStorageApplyDto.setData(null);
//        //发送WMS申请入库请求终点储位
//        String destinationStorageCode = wcsReportService.inboundStorageApply(inboundStorageApplyDto);
//        TestVo testVo = wcsReportService.wmsInventoryInformation(palletCode);
//        Integer code = testVo.getCode();
//        StringBuilder sb = new StringBuilder();
//        if (code == 200){
//            List<MaterialDao> materialDaoList = testVo.getData();
//            if (!materialDaoList.isEmpty()){
//                List<String> materialCodeList = materialDaoList.stream().map(MaterialDao::getMaterialCode).distinct().collect(Collectors.toList());
//                for (String materialCode : materialCodeList) {
//                    if (sb.length() >0){
//                        sb.append(",");
//                    }
//                    sb.append(materialCode);
//                }
//            }else {
//                return ReturnVo.ng("在WMS未找到库存信息");
//            }
//        }else {
//            return ReturnVo.ng("在WMS未找到库存信息");
//        }
//        pda.info("1楼回库请求参数：{},返回结果：{}", inboundStorageApplyDto, destinationStorageCode);
//        if (destinationStorageCode != null) {
//            //储位绑定栈板
//            CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
//            carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
//            carrierUnbindDto.setSlotCode(storageCode);
//            carrierUnbindDto.setCarrierCategory("PALLET");
//            carrierUnbindDto.setCarrierType("1");
//            carrierUnbindDto.setInvoke(TaskType.BIND.getMessage());
//            agvSendService.carrierUnbind(carrierUnbindDto);
//
//            //发送AGV起点-中间点-终点
//            AgvTaskSubmitDto agvTaskSubmitDto = new AgvTaskSubmitDto();
//            //todo 任务类型，根据现场情况来定
//            agvTaskSubmitDto.setTaskType(TaskType.PF_FMR_TASK_CONTINUE.getMessage());
//            ArrayList<TargetRoute> targetRouteList = new ArrayList<>();
//            TargetRoute targetRoute = new TargetRoute();
//            TargetRoute targetRoutes = new TargetRoute();
//            //添加起点
//            targetRoute.setSeq(0);
//            targetRoute.setType(TaskType.SITE.getMessage());
//            targetRoute.setCode(storageCode);
//            //添加终点
//            targetRoutes.setSeq(1);
//            targetRoutes.setType(TaskType.SITE.getMessage());
//            targetRoutes.setCode(TaskType.ONE_FLOOR_RETURN_TO_STORAGE_LOCATION.getMessage());
//            targetRouteList.add(targetRoute);
//            targetRouteList.add(targetRoutes);
//            agvTaskSubmitDto.setTargetRoute(targetRouteList);
//            String inboundCode = String.valueOf(idWorker.nextId());
//            agvTaskSubmitDto.setRobotTaskCode(inboundCode);
//            agvTaskSubmitDto.setInitPriority(99);
//            String taskCode = agvSendService.agvTaskSubmit(agvTaskSubmitDto);
//            if (taskCode != null) {
//                //创建回库任务
//                WcsInboundMission wcsInboundMission = new WcsInboundMission();
//                wcsInboundMission.setInboundCode(inboundCode);
//                wcsInboundMission.setMissionStatus(TaskStatus.task_send.getStatus());
//                wcsInboundMission.setContainerCode(palletCode);
//                wcsInboundMission.setSource(storageCode);
//                wcsInboundMission.setDestination(destinationStorageCode);
//                wcsInboundMission.setContainerType(4);
//                wcsInboundMission.setCreateTime(LocalDateTime.now());
//                wcsInboundMission.setUpdateTime(LocalDateTime.now());
//                wcsInboundMission.setInboundType(TaskType.circle_library_sorting.getStatus());
//                wcsInboundMission.setIsNest(1);
//                wcsInboundMission.setIsPlc(0);
//                String materialCode = sb.toString();
//                wcsInboundMission.setMaterialCode(materialCode);
//                boolean b = wcsInboundMissionService.insertInbound(wcsInboundMission);
//                if (!b) {
//                    pda.error("创建入库任务失败");
//                    throw new RuntimeException("创建入库任务失败");
//                }
//            }else {
//                CancelInboundStorageDto cancelInboundStorageDto = new CancelInboundStorageDto();
//                cancelInboundStorageDto.setStorageId(destinationStorageCode);
//                cancelInboundStorageDto.setContainerCode(palletCode);
//                cancelInboundStorageDto.setNest(true);
//                //任务下发失败，通知WMS取消入库申请储位
//                boolean b = wcsReportService.cancelInboundStorage(cancelInboundStorageDto);
//                return ReturnVo.ng("任务下发,AGV接收任务失败");
//            }
//            return ReturnVo.OK();
//        }
//        return ReturnVo.ng("未找到合适的终点储位");
//    }

    //扫储位码释放储位
    @Override
    public ReturnVo pdaStorageRelease(String storage) {
        IwsSOutside iwsSOutside = iwsSOutsideService.selectStorageCode(storage);
        if (iwsSOutside == null) {
            return ReturnVo.ng("当前储位不是库外储位,释放失败");
        }
        boolean b = iwsSOutsideService.updateStatus(storage, null, 0);
        if (!b) {
            return ReturnVo.ng("数据库异常,释放失败");
        }
        return ReturnVo.OK();
    }

    @Override
    public ReturnVo vehicleNesting(String containerCode) {
        //查询嵌套信息
        List<NestingMiddleTable> nestingMiddleTables = nestingMiddleTableService.selectContainerCode(containerCode);
        if (nestingMiddleTables.isEmpty()) {
            return ReturnVo.ng("未查询到嵌套信息");
        } else {
            long rawMaterialsQ = nestingMiddleTables.stream().filter(f -> f.getMaterial().equals(TaskType.MATERIAL_Q.getMessage())).count();
            if (rawMaterialsQ != 0) {
                //判断是否自检
                long rawMaterialsQQualified = nestingMiddleTables.stream().filter(f -> f.getMaterial().equals(TaskType.MATERIAL_Q.getMessage()) && f.getSelfCheckStatus() == 1).count();
                if (rawMaterialsQ == rawMaterialsQQualified) {
                    return ReturnVo.OK();
                }
                return ReturnVo.ng("原物料Q未自检");
            }
        }
        return ReturnVo.ng("未查询到嵌套信息");
    }

    @Transactional
    @Override
    public ReturnVo artificialInbound(ArtificialInboundDto artificialInboundDto) {
        pda.info("人工入库请求参数：{}",artificialInboundDto);
        String containerCode = artificialInboundDto.getContainerCode();
        String storageCode = artificialInboundDto.getStorageCode();
        //向wms发送储位申请入库
        String floor = storageCode.substring(0, 2);
        InboundStorageApplyDto1 inboundStorageApplyDto = new InboundStorageApplyDto1();
        inboundStorageApplyDto.setContainerCode(containerCode);
        inboundStorageApplyDto.setFloor(floor);
        inboundStorageApplyDto.setNest(false);
        List<NestingMiddleTable> nestingMiddleTables = nestingMiddleTableService.selectContainerCode(containerCode);
        ArrayList<MaterialDao> materialDaos = new ArrayList<>();
        for (NestingMiddleTable nestingMiddleTable : nestingMiddleTables) {
            MaterialDao materialDao = new MaterialDao();
            BeanUtils.copyProperties(nestingMiddleTable,materialDao);
            materialDaos.add(materialDao);
        }
        inboundStorageApplyDto.setData(materialDaos);
        String destination = wcsReportService.inboundStorageApply(inboundStorageApplyDto);
        if (destination !=null){
            StringBuilder sb = new StringBuilder();
            List<String> materialCodeList = nestingMiddleTables.stream().map(NestingMiddleTable::getMaterialCode).distinct().collect(Collectors.toList());
            for (String materialCode : materialCodeList) {
                if (sb.length() >0){
                    sb.append(",");
                }
                sb.append(materialCode);
            }
            String inboundCode = String.valueOf(idWorker.nextId());
            //储位绑定栈板
            CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
            carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
            carrierUnbindDto.setSlotCode(storageCode);
            carrierUnbindDto.setCarrierCategory("PALLET");
            carrierUnbindDto.setCarrierType("1");
            carrierUnbindDto.setInvoke(TaskType.BIND.getMessage());
            agvSendService.carrierUnbind(carrierUnbindDto);
            //下发agv任务
            AgvTaskSubmitDto agvTaskSubmitDto = new AgvTaskSubmitDto();
            //todo 任务类型，根据现场情况来定
            agvTaskSubmitDto.setTaskType(TaskType.PF_FMR_COMMON.getMessage());
            ArrayList<TargetRoute> targetRouteList = new ArrayList<>();
            TargetRoute targetRoute = new TargetRoute();
            TargetRoute targetRoutes = new TargetRoute();
            //添加起点
            targetRoute.setSeq(0);
            targetRoute.setType(TaskType.STORAGE.getMessage());
            targetRoute.setCode(storageCode);
            //添加终点
            targetRoutes.setSeq(1);
            targetRoutes.setType(TaskType.STORAGE.getMessage());
            targetRoutes.setCode(destination);
            targetRouteList.add(targetRoute);
            targetRouteList.add(targetRoutes);
            agvTaskSubmitDto.setTargetRoute(targetRouteList);
            agvTaskSubmitDto.setRobotTaskCode(inboundCode);
            agvTaskSubmitDto.setInitPriority(90);
            String taskCode = agvSendService.agvTaskSubmit(agvTaskSubmitDto);
            if (taskCode == null){
                //通知WMS取消入庫任務
                CancelInboundStorageDto cancelInboundStorageDto = new CancelInboundStorageDto();
                cancelInboundStorageDto.setStorageId(destination);
                cancelInboundStorageDto.setContainerCode(containerCode);
                cancelInboundStorageDto.setNest(false);
                boolean b = wcsReportService.cancelInboundStorage(cancelInboundStorageDto);
                if (b){
                    pda.error("下发任务给AGV失败");
                    throw new RuntimeException("下发任务给AGV失败,数据回滚");
                }
            }else {
                //创建入库任务
                WcsInboundMission wcsInboundMission = new WcsInboundMission();
                wcsInboundMission.setInboundCode(inboundCode);
                wcsInboundMission.setMissionStatus(TaskStatus.task_send.getStatus());
                wcsInboundMission.setContainerCode(containerCode);
                wcsInboundMission.setSource(storageCode);
                wcsInboundMission.setDestination(destination);
                if (TaskType.ONE_FLOOR.getMessage().equals(floor)){
                    wcsInboundMission.setContainerType(TaskType.PALLET.getStatus());
                }else if ((TaskType.TWO_FLOOR.getMessage().equals(floor))){
                    wcsInboundMission.setContainerType(TaskType.WORKBIN.getStatus());
                }else if ((TaskType.THREE_FLOOR.getMessage().equals(floor))){
                    wcsInboundMission.setContainerType(TaskType.THREE_WORKBIN.getStatus());
                }
                wcsInboundMission.setCreateTime(LocalDateTime.now());
                wcsInboundMission.setUpdateTime(LocalDateTime.now());
                wcsInboundMission.setInboundType(TaskType.inbound_ordinary.getStatus());
                wcsInboundMission.setPriority(90);
                wcsInboundMission.setIsNest(0);
                wcsInboundMission.setIsPlc(0);
                String materialCode = sb.toString();
                wcsInboundMission.setMaterialCode(materialCode);
                wcsInboundMissionService.insertInbound(wcsInboundMission);
            }
            return ReturnVo.OK();
        }
        return ReturnVo.ng("入库未找到合适储位");
    }
}
